import { loadTexture, BaseModel } from '../plugin';

export default class Floor extends BaseModel {
  constructor(options) {
    super();

    this.options = {
      color: 0x57fff7,
      ...options,
    };

    this.#init();
  }

  #init() {
    const { color } = this.options;

    const outerCircle = this.#createOuterCircle(color);
    outerCircle.renderOrder = 2;
    this.object.add(outerCircle);

    const innerCircle = this.#createInnerCircle(color);
    innerCircle.renderOrder = 3;
    this.object.add(innerCircle);

    const videoMesh1 = this.#createVideoMesh1(0x9edeec);
    videoMesh1.position.set(27, -12, 0);
    videoMesh1.renderOrder = 4;
    this.object.add(videoMesh1);

    const videoMesh2 = this.#createVideoMesh2(0x9edeec);
    videoMesh2.position.set(-27, 12, 0);
    videoMesh2.renderOrder = 4;
    this.object.add(videoMesh2);

    const mask = this.#createMask();
    mask.renderOrder = 9;
    this.object.add(mask);
  }

  #createMask() {
    const geometry = new THREE.PlaneGeometry(100, 100);
    const material = new THREE.ShaderMaterial({
      vertexShader: `
        varying vec2 vUv;

        void main() {
          vUv = uv;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
      `,
      fragmentShader: `
        varying vec2 vUv;

        void main() {
          float base = 0.2;
          float alpha = clamp(0.0, 1.0, (distance(vUv, vec2(0.5)) - base) * 1.0 / (0.5 - base));
          gl_FragColor = vec4(0.0, 0.0, 0.0, alpha);
        }
      `,
      transparent: true,
      // depthTest: false,
    });

    return new THREE.Mesh(geometry, material);
  }

  #createInnerCircle(color) {
    const url = require('./assets/innerCircle.png');
    const texture = loadTexture(url);

    const geometry = new THREE.PlaneGeometry(50, 50);
    const material = new THREE.MeshBasicMaterial({
      color,
      map: texture,
      opacity: 0.4,
      transparent: true,
    });
    const mesh = new THREE.Mesh(geometry, material);

    texture.center.set(0.5, 0.5);
    const tween = new TWEEN.Tween(texture, this.tweenGroup).to({ rotation: -Math.PI * 2 }, 15 * 1000).repeat(Infinity);
    this.tweenList.push(tween);

    return mesh;
  }

  #createOuterCircle(color) {
    const url = require('./assets/outerCircle.png');
    const texture = loadTexture(url);

    const geometry = new THREE.PlaneGeometry(50, 50);
    const material = new THREE.MeshBasicMaterial({
      color,
      map: texture,
      opacity: 0.8,
      transparent: true,
    });
    const mesh = new THREE.Mesh(geometry, material);

    texture.center.set(0.5, 0.5);
    const tween = new TWEEN.Tween(texture, this.tweenGroup).to({ rotation: Math.PI * 2 }, 50 * 1000).repeat(Infinity);
    this.tweenList.push(tween);

    return mesh;
  }

  #createVideoMesh1(color) {
    const url = require('./assets/animate.mov');
    const texture = this.#getVideoTexture(url);

    const geometry = new THREE.PlaneGeometry(10, 4);
    const material = new THREE.MeshBasicMaterial({
      color,
      alphaMap: texture,
      transparent: true,
      // depthTest: false,
    });

    return new THREE.Mesh(geometry, material);
  }

  #createVideoMesh2(color) {
    const url = require('./assets/animate2.mov');
    const texture = this.#getVideoTexture(url);

    const geometry = new THREE.PlaneGeometry(10, 4);
    const material = new THREE.MeshBasicMaterial({
      color,
      alphaMap: texture,
      transparent: true,
      // depthTest: false,
    });

    return new THREE.Mesh(geometry, material);
  }

  #getVideoTexture(url) {
    const video = document.createElement('video');
    video.setAttribute('autoplay', 'autoplay');
    video.setAttribute('muted', 'muted');
    video.setAttribute('loop', 'loop');
    video.src = url;
    return new THREE.VideoTexture(video);
  }
}
